package front

import (
	"encoding/json"
	red "github.com/gomodule/redigo/redis"
	"github.com/juju/errors"
	"qihuang/config"
	"qihuang/db/mysql"
	"qihuang/db/redis"
	"qihuang/loger"
	"qihuang/model"
	"qihuang/protocol"
	"qihuang/serializers"
	"strconv"
)

//文章评论详情
type ArticleCommentDetails struct {
	model.ArticleComment
}

type ArticleComments struct {
}

type CreateCommentService struct {
	ReplyToID int    `json:"reply_to_id" form:"reply_to_id"`
	ArticleID int    `json:"article_id" form:"article_id" binding:"required"`
	ParentID  int    `json:"parent_id" form:"parent_id"`
	RootID    int    `json:"root_id" form:"root_id"`
	Content   string `json:"content" form:"content" binding:"required,min=3"`
}
type CommentSerializer struct {
	Id         int               `json:"id"`
	User       model.Users       `json:"user"`
	ArticleID  int               `json:"article_id"`
	Content    string            `json:"content"`
	CreateTime string            `json:"create_time"`
	Replys     []ReplySerializer `json:"replys"`
}

type ReplySerializer struct {
	ID         int         `json:"id"`
	User       model.Users `json:"user"`
	ReplyTo    model.Users `json:"reply_to"`
	ParentID   int         `json:"parent_id"`
	RootID     int         `json:"root_id"`
	Content    string      `json:"content"`
	CreateTime string      `json:"create_time"`
}

// 序列化回复
func BuildReply(item model.ArticleComment) ReplySerializer {
	return ReplySerializer{
		ID:         item.Id,
		User:       item.User,
		ReplyTo:    item.ReplyTo,
		ParentID:   item.ParentID,
		RootID:     item.RootID,
		Content:    item.Content,
		CreateTime: item.CreateTime,
	}
}

// 序列化评论
func BuildComment(item model.ArticleComment) CommentSerializer {
	var replys []ReplySerializer
	if len(item.Replys) != 0 {
		for _, reply := range item.Replys {
			replys = append(replys, BuildReply(reply))
		}
	}
	return CommentSerializer{
		Id:         item.Id,
		User:       item.User,
		ArticleID:  item.ArticleID,
		Content:    item.Content,
		CreateTime: item.CreateTime,
		Replys:     replys,
	}
}

func BuildComments(items []model.ArticleComment) []model.ArticleComment {
	var comments []model.ArticleComment
	for _, item := range items {
		comments = append(comments, item)
	}
	return comments
}

//添加文章
func (c *CreateCommentService) Add(user *model.Users) *serializers.Response {
	comment := model.ArticleComment{
		UserID:    user.Id,
		ReplyToID: c.ReplyToID,
		ArticleID: c.ArticleID,
		ParentID:  c.ParentID,
		RootID:    c.RootID,
		Content:   c.Content,
	}

	db := mysql.Default().GetConn()
	defer db.Close()
	if err := db.Create(&comment).Error; err != nil {
		return &serializers.Response{
			Status: 1,
			Msg:    "评论失败！",
			Error:  err.Error(),
		}
	}

	// 返回当前评论的用户和   replyTo用户(如果是回复的话)
	comment.User = *user
	if comment.ReplyToID != 0 {
		var replyToUser model.Users
		if err := db.Find(&replyToUser, c.ReplyToID).Error; err != nil {
			return &serializers.Response{
				Status: 1,
				Msg:    "数据获取失败！",
				Error:  err.Error(),
			}
		}
		comment.ReplyTo = replyToUser
		return &serializers.Response{
			Status: 0,
			Msg:    "评论成功！",
			Data:   BuildReply(comment),
		}
	}

	return &serializers.Response{
		Status: 1,
		Msg:    "评论成功！",
		Data:   BuildComment(comment),
	}
}

//分页获取文章评论列表mysql
func (c *ArticleComments) GetListForMysql(page int, pageSize int, ArticleId int, fields []string) (resp *protocol.Resp) {
	resp = &protocol.Resp{Status: 1, Msg: "", Data: ""}
	db := mysql.Default().GetConn()
	defer db.Close()
	offset := (page - 1) * pageSize
	comments := make([]model.ArticleComment, 0)
	db = db.Where("status = ?  and parent_id is null", 0)
	if ArticleId > 0 {
		db = db.Where("article_id = ?", ArticleId)
	}
	if err := db.Select(fields).Offset(offset).Limit(pageSize).Order("id desc").Preload("Users").
		Find(&comments).Error; err != nil {
		loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
		resp.Msg = "系统错误"
		return resp
	}
	// 取出评论下方的回复、回复者、回复了谁
	for i := 0; i < len(comments); i++ {
		if err := db.Where("root_id=?", comments[i].Id).
			Preload("Users").Preload("ReplyTo").
			Find(&comments[i].Replys).Error; err != nil {
			loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
			resp.Status = 1
			resp.Msg = "系统错误"
			return resp
		}
	}
	resp.Status = 0
	resp.Data = comments
	return resp
}

//分页获取文章评论列表es
func (c *ArticleComments) GetListForEs(page int, pageSize int, ArticleId int, fields []string) (resp *protocol.Resp) {
	resp = &protocol.Resp{Status: 1, Msg: "", Data: ""}
	//esclient, err := es.Default()
	//if err != nil {
	//	loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
	//	resp.Status = -999
	//	resp.Msg = "系统错误"
	//	return resp
	//}
	//esconn := esclient.GetConn()
	//ctx := context.Background()
	comments := make([]model.ArticleComment, 0)

	db := mysql.Default().GetConn()
	defer db.Close()
	if ArticleId > 0 {
		db = db.Where("article_id = ?", ArticleId)
	}
	offSet := pageSize * (page - 1)
	if err := db.Limit(pageSize).Offset(offSet).Where("status = 0 and parent_id is null").Preload("Users").
		Find(&comments).Error; err != nil {
		loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
		resp.Status = 1
		resp.Msg = "系统错误"
		return resp
	}
	// 取出评论下方的回复、回复者、回复了谁
	for i := 0; i < len(comments); i++ {
		if err := db.Where("root_id=?", comments[i].Id).
			Preload("Users").Preload("ReplyTo").
			Find(&comments[i].Replys).Error; err != nil {
			loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
			resp.Status = 1
			resp.Msg = "系统错误"
			return resp
		}
	}
	//
	//query := esconn.Search().
	//	Index("myblog").
	//	Type("mb_articles").
	//	Size(page_size).
	//	From((page-1)*page_size).
	//	Sort("modify_time", false).
	//	Pretty(true)
	//boolQuery := elastic.NewBoolQuery()
	//searchQuery := boolQuery.Must(elastic.NewTermQuery("status", 1))
	//if cate_id > 0 {
	//	searchQuery = searchQuery.Filter(elastic.NewTermQuery("cate_id", cate_id))
	//}
	//query = query.Query(searchQuery)
	//result, err := query.Do(ctx)
	//if err != nil {
	//	loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
	//	resp.Status = -999
	//	resp.Msg = "系统错误"
	//	return resp
	//}
	//var typ model.Articles
	////for _, item := range result.Each(reflect.TypeOf(typ)) { //从搜索结果中取数据的方法
	//for _, item := range result.Each(reflect.TypeOf(typ)) { //从搜索结果中取数据的方法
	//	t := item.(model.Articles)
	//	t.ModifyTime = helper.DateToDateTime(t.ModifyTime)
	//	t.CreateTime = helper.DateToDateTime(t.CreateTime)
	//	articles = append(articles, t)
	//
	//}
	resp.Status = 0
	resp.Data = comments
	return resp
}

//获取文章评论详情
func (c *ArticleComments) GetArticleDetail(articleId int) (resp *protocol.Resp) {
	resp = &protocol.Resp{Status: 1, Msg: "", Data: ""}
	//articleContent := model.ArticlesContents{}
	articleDetails := ArticleDetails{}
	redisConn := redis.RedisClient.Pool.Get()
	cacheKey := "article_" + config.Configs.RedisCacheVersion + ":" + strconv.Itoa(articleId)
	if err := redisConn.Err(); err != nil {
		loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
	} else {
		cateCache, err := red.String(redisConn.Do("GET", cacheKey))
		if err != nil {
			loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
		} else {
			if cateCache != "" {
				err := json.Unmarshal([]byte(cateCache), &articleDetails)
				if err != nil {
					loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
				}
				resp.Status = 0
				resp.Data = articleDetails
				return resp
			}
		}
	}

	db := mysql.Default().GetConn()
	defer db.Close()
	if err := db.Where("id = ?", articleId).Where("status = ?", 0).First(&articleDetails).Error; err != nil {
		loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
		resp.Msg = "文章不存在"
		return resp
	}
	if articleDetails.Id <= 0 {
		resp.Msg = "文章不存在"
		return resp
	}
	//if err := db.Where("article_id = ?", articleId).First(&articleContent).Error; err != nil {
	//	loger.Loger.Error(errors.ErrorStack(errors.Trace(err)))
	//	resp.Msg = "系统错误"
	//	return resp
	//}
	resp.Status = 0
	//articleDetails.Contents = articleContent.Contents
	//articleDetails.ShowType = articleContent.ShowType
	cacheData, err := json.Marshal(articleDetails)
	if err == nil {
		redisConn.Do("set", cacheKey, string(cacheData))
		redisConn.Do("expire", cacheKey, 86400*3)
	}
	resp.Data = articleDetails
	return resp
}
